//package com.yang.lock.core;
//
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.AfterReturning;
//import org.aspectj.lang.annotation.AfterThrowing;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import com.yang.lock.annotation.YangLock;
//import com.yang.lock.handler.LockInvocationException;
//import com.yang.lock.lock.Lock;
//import com.yang.lock.lock.LockFactory;
//import com.yang.lock.model.LockInfo;
//import org.springframework.core.annotation.Order;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StringUtils;
//
//import java.lang.reflect.InvocationTargetException;
//import java.lang.reflect.Method;
//import java.util.Map;
//import java.util.Objects;
//import java.util.concurrent.ConcurrentHashMap;
//
///**
// * <p>
// * 给YangLock添加切面
// * </p>
// * @author yang
// * @date 2023/7/13
// */
//@Aspect
//@Component
//@Order(0)
//public class LockAspectHandler {
//
//    private static final Logger logger = LoggerFactory.getLogger(LockAspectHandler.class);
//
//    @Autowired
//    private LockFactory lockFactory;
//
//    @Autowired
//    private LockInfoProvider lockInfoProvider;
//
//    private final Map<String,LockRes> currentThreadLock = new ConcurrentHashMap<>();
//
//
//    @Around(value = "@annotation(yangLock)")
//    public Object around(ProceedingJoinPoint joinPoint, YangLock yangLock) throws Throwable {
//        // 获取锁的信息
//        LockInfo lockInfo = lockInfoProvider.get(joinPoint, yangLock);
//        // 获取当前锁的名称
//        String currentLock = this.getCurrentLockId(joinPoint, yangLock);
//        // 存入map
//        currentThreadLock.put(currentLock, new LockRes(lockInfo, false));
//        // 根据锁的信息获取具体的锁
//        Lock lock = lockFactory.getLock(lockInfo);
//        // 尝试获取锁
//        boolean lockRes = lock.acquire();
//        // 如果获取锁失败了，则进入失败的处理逻辑
//        if(!lockRes) {
//            if(logger.isWarnEnabled()) {
//                logger.warn("Timeout while acquiring Lock({})", lockInfo.getName());
//            }
//            // 如果自定义了获取锁失败的处理策略，则执行自定义的降级处理策略
//            if(!StringUtils.isEmpty(yangLock.customLockTimeoutStrategy())) {
//
//                return handleCustomLockTimeout(yangLock.customLockTimeoutStrategy(), joinPoint);
//
//            } else {
//                // 否则执行预定义的执行策略
//                // 注意：如果没有指定预定义的策略，默认的策略为静默啥不做处理
//                yangLock.lockTimeoutStrategy().handle(lockInfo, lock, joinPoint);
//            }
//        }
//        //给LockRes添加信息
//        currentThreadLock.get(currentLock).setLock(lock);
//        currentThreadLock.get(currentLock).setRes(true);
//
//        return joinPoint.proceed();
//    }
//
//    @AfterReturning(value = "@annotation(yangLock)")
//    public void afterReturning(JoinPoint joinPoint, YangLock yangLock) throws Throwable {
//        // 获取当前锁在map中的key
//        String currentLock = this.getCurrentLockId(joinPoint, yangLock);
//        // 释放锁
//        releaseLock(yangLock, joinPoint,currentLock);
//        // 清理内存
//        cleanUpThreadLocal(currentLock);
//    }
//
//    @AfterThrowing(value = "@annotation(yangLock)", throwing = "ex")
//    public void afterThrowing (JoinPoint joinPoint, YangLock yangLock, Throwable ex) throws Throwable {
//        // 获取当前锁在map中的key
//        String currentLock = this.getCurrentLockId(joinPoint, yangLock);
//        // 释放锁
//        releaseLock(yangLock, joinPoint,currentLock);
//        // 清理内存
//        cleanUpThreadLocal(currentLock);
//        throw ex;
//    }
//
//    /**
//     * 处理自定义加锁超时
//     */
//    private Object handleCustomLockTimeout(String lockTimeoutHandler, JoinPoint joinPoint) throws Throwable {
//
//        // 获取自定义方法
//        Method currentMethod = ((MethodSignature) joinPoint.getSignature()).getMethod();
//        // 获取目标对象
//        Object target = joinPoint.getTarget();
//
//        Method handleMethod;
//        try {
//            //根据方法名称和方法参数来获取方法
//            handleMethod = joinPoint.getTarget().getClass().getDeclaredMethod(lockTimeoutHandler, currentMethod.getParameterTypes());
//
//            handleMethod.setAccessible(true);
//        } catch (NoSuchMethodException e) {
//            throw new IllegalArgumentException("Illegal annotation param customLockTimeoutStrategy",e);
//        }
//        //获取方法参数
//        Object[] args = joinPoint.getArgs();
//
//        Object res;
//        try {
//            //反射调用
//            res = handleMethod.invoke(target, args);
//        } catch (IllegalAccessException e) {
//            throw new LockInvocationException("Fail to invoke custom lock timeout handler: " + lockTimeoutHandler ,e);
//        } catch (InvocationTargetException e) {
//            throw e.getTargetException();
//        }
//
//        return res;
//    }
//
//    /**
//     *  释放锁
//     */
//    private void releaseLock(YangLock yangLock, JoinPoint joinPoint, String currentLock) throws Throwable {
//        // 获取锁的信息
//        LockRes lockRes = currentThreadLock.get(currentLock);
//
//        if(Objects.isNull(lockRes)){
//            throw new NullPointerException("Please check whether the input parameter " +
//                    "used as the lock key value has been" +
//                    " modified in the method, which will cause the acquire" +
//                    " and release locks to have different key values and " +
//                    "throw null pointers.currentLockKey:" + currentLock);
//        }
//        if (lockRes.getRes()) {
//            // 释放锁
//            boolean releaseRes = currentThreadLock.get(currentLock).getLock().release();
//            // 当下面发生异常时，无效释放锁定两次
//            lockRes.setRes(false);
//            // 所释放失败
//            if (!releaseRes) {
//                // 处理释放锁时已超时
//                handleReleaseTimeout(yangLock, lockRes.getLockInfo(), joinPoint);
//            }
//        }
//    }
//
//    private void cleanUpThreadLocal(String currentLock) {
//        currentThreadLock.remove(currentLock);
//    }
//
//
//    /**
//     * 获取当前锁在map中的key
//     */
//    private String getCurrentLockId(JoinPoint joinPoint , YangLock yangLock){
//
//        LockInfo lockInfo = lockInfoProvider.get(joinPoint, yangLock);
//
//        return Thread.currentThread().getId() + lockInfo.getName();
//    }
//
//    /**
//     *  处理释放锁时已超时
//     */
//    private void handleReleaseTimeout(YangLock yangLock, LockInfo lockInfo, JoinPoint joinPoint) throws Throwable {
//
//        if(logger.isWarnEnabled()) {
//            logger.warn("Timeout while release Lock({})", lockInfo.getName());
//        }
//        // 判断锁释放已经超时策略
//        if(!StringUtils.isEmpty(yangLock.customReleaseTimeoutStrategy())) {
//            // 自定义释放锁时已超时的处理策略
//            handleCustomReleaseTimeout(yangLock.customReleaseTimeoutStrategy(), joinPoint);
//        } else {
//            // 走默认释放的策略，默认不做任何处理
//            yangLock.releaseTimeoutStrategy().handle(lockInfo);
//        }
//
//    }
//
//    /**
//     * 处理自定义释放锁时已超时
//     */
//    private void handleCustomReleaseTimeout(String releaseTimeoutHandler, JoinPoint joinPoint) throws Throwable {
//        // 获取方法
//        Method currentMethod = ((MethodSignature)joinPoint.getSignature()).getMethod();
//        // 获取目标对象
//        Object target = joinPoint.getTarget();
//
//        Method handleMethod;
//        try {
//            // 根据方法名称和方法参数来获取方法
//            handleMethod = joinPoint.getTarget().getClass().getDeclaredMethod(releaseTimeoutHandler, currentMethod.getParameterTypes());
//
//            handleMethod.setAccessible(true);
//        } catch (NoSuchMethodException e) {
//
//            throw new IllegalArgumentException("Illegal annotation param customReleaseTimeoutStrategy",e);
//        }
//        // 获取方法参数
//        Object[] args = joinPoint.getArgs();
//
//        try {
//            handleMethod.invoke(target, args);
//        } catch (IllegalAccessException e) {
//            throw new LockInvocationException("Fail to invoke custom release timeout handler: " + releaseTimeoutHandler, e);
//        } catch (InvocationTargetException e) {
//            throw e.getTargetException();
//        }
//    }
//
//    private static class LockRes {
//
//        private LockInfo lockInfo;
//        private Lock lock;
//        private Boolean res;
//
//        LockRes(LockInfo lockInfo, Boolean res) {
//            this.lockInfo = lockInfo;
//            this.res = res;
//        }
//
//        LockInfo getLockInfo() {
//            return lockInfo;
//        }
//
//        public Lock getLock() {
//            return lock;
//        }
//
//        public void setLock(Lock lock) {
//            this.lock = lock;
//        }
//
//        Boolean getRes() {
//            return res;
//        }
//
//        void setRes(Boolean res) {
//            this.res = res;
//        }
//
//        void setLockInfo(LockInfo lockInfo) {
//            this.lockInfo = lockInfo;
//        }
//    }
//
//
//}
